package mask_data

import (
	"crypto/md5"
	"crypto/sha256"
	"encoding/hex"
	"fmt"

	"github.com/example-user/go-pocket-etl/pkg/core"
	"github.com/example-user/go-pocket-etl/pkg/factory"
)

// init 实现了组件的自注册。
func init() {
	factory.RegisterProcessor("mask_data", NewProcessor)
}

// Processor 实现了 core.Processor 接口，用于对指定列的敏感数据进行脱敏。
// 它通过单向哈希算法将原始值替换为一个固定长度的哈希值，实现数据的假名化（pseudonymization）。
// 这对于在保留数据分析能力的同时保护用户隐私至关重要。
type Processor struct {
	column string // 要脱敏的列名。
	method string // 脱敏方法（哈希算法）。
}

// NewProcessor 是 mask_data.Processor 的构造函数，由工厂调用。
func NewProcessor() core.Processor {
	return &Processor{}
}

// Open 从配置中解析需要脱敏的列和所用的哈希方法。
//
// YAML 配置示例:
//   - type: mask_data
//     params:
//     column: "user_email"
//     method: "sha256"
//
// 支持的脱敏方法 (`method`):
// - "md5"
// - "sha256"
func (p *Processor) Open(config map[string]interface{}) error {
	column, ok := config["column"].(string)
	if !ok || column == "" {
		return fmt.Errorf("mask_data processor: config is missing or has invalid 'column'")
	}
	p.column = column

	method, ok := config["method"].(string)
	if !ok || method == "" {
		return fmt.Errorf("mask_data processor: config is missing or has invalid 'method'")
	}
	p.method = method

	return nil
}

// Process 对记录进行处理，使用指定的哈希算法替换原始值。
//
// 设计与安全说明:
//   - 如果列不存在或值为 nil，处理器会静默忽略，以保证管道的弹性。
//   - 任何类型的值都会先被转换为字符串，然后再进行哈希计算。
//   - **安全警告**: 这是一种单向哈希，不是加密。相同的输入值将始终产生相同的输出哈希值。
//     这对于保持数据关联性很有用，但也意味着如果攻击者能够猜到原始值（例如，对于低复杂度的输入），
//     他们可以通过彩虹表攻击来反查。请勿将其用于需要可逆加密的场景。
func (p *Processor) Process(record core.Record) (core.Record, error) {
	originalValue, ok := record[p.column]
	if !ok {
		// 如果列不存在，静默忽略。
		return record, nil
	}

	if originalValue == nil {
		// 不处理 nil 值。
		return record, nil
	}

	// 将原始值转换为字符串以进行哈希。
	valStr := fmt.Sprintf("%v", originalValue)
	var maskedValue string

	switch p.method {
	case "md5":
		hasher := md5.New()
		hasher.Write([]byte(valStr))
		maskedValue = hex.EncodeToString(hasher.Sum(nil))
	case "sha256":
		hasher := sha256.New()
		hasher.Write([]byte(valStr))
		maskedValue = hex.EncodeToString(hasher.Sum(nil))
	default:
		return nil, fmt.Errorf("mask_data processor: unsupported hashing method: '%s'", p.method)
	}

	// 使用脱敏后的新值更新记录。
	record[p.column] = maskedValue

	return record, nil
}

// Close 是一个无操作（no-op）方法，因为此处理器是无状态的。
func (p *Processor) Close() error {
	return nil
}
